home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 001 / pibt32s2.arc / PIBASYN1.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-11-02  |  34.3 KB  |  721 lines

  1. (*----------------------------------------------------------------------*)
  2. (*         PIBASYNC.PAS   --- Asynchronous I/O for Turbo Pascal         *)
  3. (*----------------------------------------------------------------------*)
  4. (*                                                                      *)
  5. (*  Author:  Philip R. Burns                                            *)
  6. (*                                                                      *)
  7. (*  Version: 1.0   (January, 1985)                                      *)
  8. (*           2.0   (June, 1985)                                         *)
  9. (*           2.1   (July, 1985)                                         *)
  10. (*           3.0   (October, 1985)                                      *)
  11. (*           3.1   (October, 1985)                                      *)
  12. (*           3.2   (November, 1985)                                     *)
  13. (*                                                                      *)
  14. (*  Systems: For MS-DOS on IBM PCs and close compatibles only.          *)
  15. (*           Note:  I have checked these on Zenith 151s under           *)
  16. (*                  MSDOS 2.1 and IBM PCs under PCDOS 2.0.              *)
  17. (*                                                                      *)
  18. (*  History: Some of these routines are based upon ones written by:     *)
  19. (*                                                                      *)
  20. (*              Alan Bishop                                             *)
  21. (*              C. J. Dunford                                           *)
  22. (*              Michael Quinlan                                         *)
  23. (*                                                                      *)
  24. (*           I have cleaned up these other authors' code, fixed some    *)
  25. (*           bugs, and added many new features.                         *)
  26. (*                                                                      *)
  27. (*           Suggestions for improvements or corrections are welcome.   *)
  28. (*           Please leave messages on Gene Plantz's BBS (312) 882 4145  *)
  29. (*           or Ron Fox's BBS (312) 940 6496.                           *)
  30. (*                                                                      *)
  31. (*           If you use this code in your own programs, please be nice  *)
  32. (*           and give all of us credit.                                 *)
  33. (*                                                                      *)
  34. (*----------------------------------------------------------------------*)
  35. (*                                                                      *)
  36. (*  Routines:                                                           *)
  37. (*                                                                      *)
  38. (*     Async_Init             ---    Performs initialization.           *)
  39. (*     Async_Check_CTS        ---    Turn CTS check on/off              *)
  40. (*     Async_Clear_Errors     ---    Clear pending serial port errors   *)
  41. (*     Async_Reset_Port       ---    Resets UART parameters for port    *)
  42. (*     Async_Open             ---    Sets up COM port                   *)
  43. (*     Async_Close            ---    Closes down COM port               *)
  44. (*     Async_Carrier_Detect   ---    Checks for modem carrier detect    *)
  45. (*     Async_Carrier_Drop     ---    Checks for modem carrier drop      *)
  46. (*     Async_Buffer_Check     ---    Checks if character in COM buffer  *)
  47. (*     Async_Buffer_Full      ---    Checks if async buffer nearly full *)
  48. (*     Async_Term_Ready       ---    Toggles terminal ready status      *)
  49. (*     Async_Receive          ---    Reads character from COM buffer    *)
  50. (*     Async_Receive_With_Timeout                                       *)
  51. (*                            ---    Receives char. with timeout check  *)
  52. (*     Async_Ring_Detect      ---    If ringing detected                *)
  53. (*     Async_Send             ---    Transmits char over COM port       *)
  54. (*     Async_Send_String      ---    Sends string over COM port         *)
  55. (*     Async_Send_String_With_Delays                                    *)
  56. (*                            ---    Sends string with timed delays     *)
  57. (*     Async_Send_Break       ---    Sends break (attention) signal     *)
  58. (*     Async_Percentage_Used  ---    Returns percentage com buffer used *)
  59. (*     Async_Purge_Buffer     ---    Purges receive buffer              *)
  60. (*                                                                      *)
  61. (*----------------------------------------------------------------------*)
  62. (*                                                                      *)
  63. (*      PIBASYNC.PAS was split into PIBASYN1.PAS and PIBASYN2.PAS at    *)
  64. (*      version 3.2 of PibTerm.                                         *)
  65. (*                                                                      *)
  66. (*----------------------------------------------------------------------*)
  67.  
  68.  
  69. (*----------------------------------------------------------------------*)
  70. (*                                                                      *)
  71. (*                  COMMUNICATIONS HARDWARE ADDRESSES                   *)
  72. (*                                                                      *)
  73. (*        These are specific to IBM PCs and close compatibles.          *)
  74. (*                                                                      *)
  75. (*----------------------------------------------------------------------*)
  76.  
  77. CONST
  78.  
  79.    UART_THR = $00;       (* offset from base of UART Registers for IBM PC *)
  80.    UART_RBR = $00;
  81.    UART_IER = $01;
  82.    UART_IIR = $02;
  83.    UART_LCR = $03;
  84.    UART_MCR = $04;
  85.    UART_LSR = $05;
  86.    UART_MSR = $06;
  87.  
  88.    I8088_IMR = $21;      (* port address of the Interrupt Mask Register *)
  89.  
  90.    COM1_Base = $03F8;    (* port addresses for the UART *)
  91.    COM2_Base = $02F8;
  92.  
  93.    COM1_Irq = 4;         (* Interrupt line for the UART *)
  94.    COM2_Irq = 3;
  95.  
  96. CONST
  97.  
  98.    Async_DSeg_Save : INTEGER = 0;  (* Save DS reg in Code Segment for *)
  99.                                    (* interrupt routine               *)
  100.  
  101. (*----------------------------------------------------------------------*)
  102. (*                                                                      *)
  103. (*                   COMMUNICATIONS BUFFER VARIABLES                    *)
  104. (*                                                                      *)
  105. (*     The Communications Buffer is implemented as a circular (ring)    *)
  106. (*     buffer, or double-ended queue.  The asynchronous I/O routines    *)
  107. (*     enter characters in the buffer as they are received.  Higher-    *)
  108. (*     level routines may extract characters from the buffer.           *)
  109. (*                                                                      *)
  110. (*     Note that this buffer is used for input only;  output is done    *)
  111. (*     on a character-by-character basis.                               *)
  112. (*                                                                      *)
  113. (*----------------------------------------------------------------------*)
  114.  
  115. CONST
  116.  
  117.    Async_Buffer_Max    = 4095;       (* Size of Communications Buffer   *)
  118.    TimeOut             = 256;        (* TimeOut value                   *)
  119.  
  120. VAR
  121.                                      (* Communications Buffer Itself *)
  122.  
  123.    Async_Buffer          : ARRAY[0..Async_Buffer_Max] OF CHAR;
  124.  
  125.    Async_Open_Flag       : BOOLEAN;  (* true if Open but no Close         *)
  126.    Async_Port            : INTEGER;  (* current Open port number (1 or 2) *)
  127.    Async_Base            : INTEGER;  (* base for current open port        *)
  128.    Async_Irq             : INTEGER;  (* irq for current open port         *)
  129.  
  130.    Async_Buffer_Overflow : BOOLEAN;  (* True if buffer overflow has happened *)
  131.    Async_Buffer_Used     : INTEGER;
  132.    Async_MaxBufferUsed   : INTEGER;
  133.  
  134.                                      (* Async_Buffer empty if Head = Tail    *)
  135.    Async_Buffer_Head    : INTEGER;   (* Loc in Async_Buffer to put next char *)
  136.    Async_Buffer_Tail    : INTEGER;   (* Loc in Async_Buffer to get next char *)
  137.    Async_Buffer_NewTail : INTEGER;
  138.  
  139.    Async_XOFF_Sent      : BOOLEAN    (* If XOFF sent                         *);
  140.    Async_Baud_Rate      : INTEGER    (* Current baud rate                    *);
  141.  
  142. CONST
  143.    Async_XON            : CHAR = ^Q  (* XON character                        *);
  144.    Async_XOFF           : CHAR = ^S  (* XOFF character                       *);
  145.    Async_Do_CTS         : BOOLEAN    (* TRUE to do clear-to-send checking    *)
  146.                           = TRUE;
  147.    Async_Do_DSR         : BOOLEAN    (* TRUE to do data-set-ready checking   *)
  148.                           = FALSE;
  149.  
  150. (*----------------------------------------------------------------------*)
  151. (*                BIOS_RS232_Init --- Initialize UART                   *)
  152. (*----------------------------------------------------------------------*)
  153.  
  154. PROCEDURE BIOS_RS232_Init( ComPort, ComParm : INTEGER );
  155.  
  156. (*----------------------------------------------------------------------*)
  157. (*                                                                      *)
  158. (*     Procedure:  BIOS_RS232_Init                                      *)
  159. (*                                                                      *)
  160. (*     Purpose:    Issues interrupt $14 to initialize the UART          *)
  161. (*                                                                      *)
  162. (*     Calling Sequence:                                                *)
  163. (*                                                                      *)
  164. (*        BIOS_RS232_Init( ComPort, ComParm : INTEGER );                *)
  165. (*                                                                      *)
  166. (*           ComPort  --- Communications Port Number (1 or 2)           *)
  167. (*           ComParm  --- Communications Parameter Word                 *)
  168. (*                                                                      *)
  169. (*      Calls:   INTR   (to perform BIOS interrupt $14)                 *)
  170. (*                                                                      *)
  171. (*----------------------------------------------------------------------*)
  172.  
  173. VAR
  174.    Regs: RegPack;
  175.  
  176. BEGIN   (* BIOS_RS232_Init *)
  177.  
  178.    WITH Regs DO
  179.       BEGIN
  180.          Ax := ComParm AND $00FF;  (* AH=0; AL=ComParm   *)
  181.          Dx := ComPort;            (* Port number to use *)
  182.          INTR($14, Regs);
  183.       END;
  184.  
  185. END    (* BIOS_RS232_Init *);
  186.  
  187.  
  188. (*----------------------------------------------------------------------*)
  189. (*             DOS_Set_Intrpt --- Call DOS to set interrupt vector      *)
  190. (*----------------------------------------------------------------------*)
  191.  
  192. PROCEDURE DOS_Set_Intrpt( v, s, o : INTEGER );
  193.  
  194. (*----------------------------------------------------------------------*)
  195. (*                                                                      *)
  196. (*     Procedure:  DOS_Set_Intrpt                                       *)
  197. (*                                                                      *)
  198. (*     Purpose:    Calls DOS to set interrupt vector                    *)
  199. (*                                                                      *)
  200. (*     Calling Sequence:                                                *)
  201. (*                                                                      *)
  202. (*        DOS_Set_Intrpt( v, s, o : INTEGER );                          *)
  203. (*                                                                      *)
  204. (*           v --- interrupt vector number to set                       *)
  205. (*           s --- segment address of interrupt routine                 *)
  206. (*           o --- offset address of interrupt routine                  *)
  207. (*                                                                      *)
  208. (*      Calls:   MSDOS   (to set interrupt)                             *)
  209. (*                                                                      *)
  210. (*----------------------------------------------------------------------*)
  211.  
  212. VAR
  213.    Regs : Regpack;
  214.  
  215. BEGIN   (* DOS_Set_Intrpt *)
  216.  
  217.    WITH Regs DO
  218.       BEGIN
  219.          Ax := $2500 + ( v AND $00FF );
  220.          Ds := s;
  221.          Dx := o;
  222.          MsDos( Regs );
  223.       END;
  224.  
  225. END    (* DOS_Set_Intrpt *);
  226.  
  227. (*----------------------------------------------------------------------*)
  228. (*               Async_Isr --- Interrupt Service Routine                *)
  229. (*----------------------------------------------------------------------*)
  230.  
  231. PROCEDURE Async_Isr;
  232.  
  233. (*----------------------------------------------------------------------*)
  234. (*                                                                      *)
  235. (*     Procedure:  Async_Isr                                            *)
  236. (*                                                                      *)
  237. (*     Purpose:    Invoked when UART has received character from        *)
  238. (*                 communications line  (asynchronous)                  *)
  239. (*                                                                      *)
  240. (*     Calling Sequence:                                                *)
  241. (*                                                                      *)
  242. (*        Async_Isr;                                                    *)
  243. (*                                                                      *)
  244. (*           --- Called asyncronously only!!!!!!                        *)
  245. (*                                                                      *)
  246. (*     Remarks:                                                         *)
  247. (*                                                                      *)
  248. (*        This is Michael Quinlan's version of the interrupt handler.   *)
  249. (*                                                                      *)
  250. (*----------------------------------------------------------------------*)
  251.  
  252. BEGIN   (* Async_Isr *)
  253.  
  254.   (*  NOTE: on entry, Turbo Pascal has already PUSHed BP and SP  *)
  255.  
  256.   INLINE(
  257.       (* save all registers used *)
  258.  
  259.           $50/$53/$51/$52/$56/$57/$1E/$06/$FB/
  260.  
  261.       (* set up the DS register to point to Turbo Pascal's data segment *)
  262.     $2E/$FF/$36/Async_Dseg_Save/   (* PUSH CS:Async_Dseg_Save *)
  263.     $1F/                           (* POP DS *)
  264.       (* get the incoming character *)
  265.       (* Async_Buffer[Async_Buffer_Head] := Chr(Port[UART_RBR + Async_Base]); *)
  266.     $8B/$16/Async_Base/            (* MOV DX,Async_Base *)
  267.     $EC/                           (* IN AL,DX *)
  268.     $8B/$1E/Async_Buffer_Head/     (* MOV BX,Async_Buffer_Head *)
  269.     $88/$87/Async_Buffer/          (* MOV Async_Buffer[BX],AL *)
  270.       (* Async_Buffer_NewHead := Async_Buffer_Head + 1; *)
  271.     $43/                           (* INC BX *)
  272.       (* if Async_Buffer_NewHead > Async_Buffer_Max then
  273.           Async_Buffer_NewHead := 0; *)
  274.     $81/$FB/Async_Buffer_Max/      (* CMP BX,Async_Buffer_Max *)
  275.     $7E/$02/                       (* JLE L001 *)
  276.     $33/$DB/                       (* XOR BX,BX *)
  277.       (* if Async_Buffer_NewHead = Async_Buffer_Tail then
  278.           Async_Buffer_Overflow := TRUE
  279.         else *)
  280. (*L001:*)
  281.     $3B/$1E/Async_Buffer_Tail/     (* CMP BX,Async_Buffer_Tail *)
  282.     $75/$08/                       (* JNE L002 *)
  283.     $C6/$06/Async_Buffer_Overflow/$01/ (* MOV Async_Buffer_Overflow,1 *)
  284.     $90/                           (* NOP generated by assembler for some reason *)
  285.     $EB/$16/                       (* JMP SHORT L003 *)
  286.       (* begin
  287.           Async_Buffer_Head := Async_Buffer_NewHead;
  288.           Async_Buffer_Used := Async_Buffer_Used + 1;
  289.           if Async_Buffer_Used > Async_MaxBufferUsed then
  290.             Async_MaxBufferUsed := Async_Buffer_Used
  291.         end; *)
  292. (*L002:*)
  293.     $89/$1E/Async_Buffer_Head/     (* MOV Async_Buffer_Head,BX *)
  294.     $FF/$06/Async_Buffer_Used/     (* INC Async_Buffer_Used *)
  295.     $8B/$1E/Async_Buffer_Used/     (* MOV BX,Async_Buffer_Used *)
  296.     $3B/$1E/Async_MaxBufferUsed/   (* CMP BX,Async_MaxBufferUsed *)
  297.     $7E/$04/                       (* JLE L003 *)
  298.     $89/$1E/Async_MaxBufferUsed/   (* MOV Async_MaxBufferUsed,BX *)
  299. (*L003:*)
  300.       (* disable interrupts *)
  301.     $FA/                           (* CLI *)
  302.       (* Port[$20] := $20; *)  (* use non-specific EOI *)
  303.     $B0/$20/                       (* MOV AL,20h *)
  304.     $E6/$20/                       (* OUT 20h,AL *)
  305.       (* restore the registers then use IRET to return *)
  306.       (* the last two POPs are required because Turbo Pascal PUSHes these regs
  307.         before we get control.  The manual doesn't say so, but that is what
  308.         really happens *)
  309.     $07/$1F/$5F/$5E/$5A/$59/$5B/$58/$8B/$E5/$5D/
  310.     $CF)                           (* IRET *)
  311.  
  312. END    (* Async_Isr *);
  313.  
  314. (*----------------------------------------------------------------------*)
  315. (*               Async_Init --- Initialize Asynchronous VARiables       *)
  316. (*----------------------------------------------------------------------*)
  317.  
  318. PROCEDURE Async_Init;
  319.  
  320. (*----------------------------------------------------------------------*)
  321. (*                                                                      *)
  322. (*     Procedure:  Async_Init                                           *)
  323. (*                                                                      *)
  324. (*     Purpose:    Initializes variables                                *)
  325. (*                                                                      *)
  326. (*     Calling Sequence:                                                *)
  327. (*                                                                      *)
  328. (*        Async_Init;                                                   *)
  329. (*                                                                      *)
  330. (*     Calls:  None                                                     *)
  331. (*                                                                      *)
  332. (*----------------------------------------------------------------------*)
  333.  
  334. BEGIN   (* Async_Init *)
  335.  
  336.   Async_DSeg_Save       := DSeg;
  337.   Async_Open_Flag       := FALSE;
  338.   Async_Buffer_Overflow := FALSE;
  339.   Async_Buffer_Used     := 0;
  340.   Async_MaxBufferUsed   := 0;
  341.   Async_XOFF_Sent       := FALSE;
  342.   Async_Buffer_Head     := 0;
  343.   Async_Buffer_Tail     := 0;
  344.  
  345. END     (* Async_Init *);
  346.  
  347. (*----------------------------------------------------------------------*)
  348. (*               Async_Close --- Close down communications interrupts   *)
  349. (*----------------------------------------------------------------------*)
  350.  
  351. PROCEDURE Async_Close;
  352.  
  353. (*----------------------------------------------------------------------*)
  354. (*                                                                      *)
  355. (*     Procedure:  Async_Close                                          *)
  356. (*                                                                      *)
  357. (*     Purpose:    Resets interrupt system when UART interrupts         *)
  358. (*                 are no longer needed.                                *)
  359. (*                                                                      *)
  360. (*     Calling Sequence:                                                *)
  361. (*                                                                      *)
  362. (*        Async_Close;                                                  *)
  363. (*                                                                      *)
  364. (*     Calls:  None                                                     *)
  365. (*                                                                      *)
  366. (*----------------------------------------------------------------------*)
  367.  
  368. VAR
  369.    i : INTEGER;
  370.    m : INTEGER;
  371.  
  372. BEGIN  (* Async_Close *)
  373.  
  374.    IF Async_Open_Flag THEN
  375.       BEGIN
  376.  
  377.                      (* disable the IRQ on the 8259 *)
  378.  
  379.          INLINE($FA);                 (* disable interrupts *)
  380.  
  381.          i := Port[I8088_IMR];        (* get the interrupt mask register *)
  382.          m := 1 SHL Async_Irq;        (* set mask to turn off interrupt  *)
  383.          Port[I8088_IMR] := i OR m;
  384.  
  385.                      (* disable the 8250 data ready interrupt *)
  386.  
  387.          Port[UART_IER + Async_Base] := 0;
  388.  
  389.                      (* disable OUT2 on the 8250 *)
  390.  
  391.          Port[UART_MCR + Async_Base] := 0;
  392.  
  393.          INLINE($FB);                 (* enable interrupts *)
  394.  
  395.                      (* re-initialize our data areas so we know *)
  396.                      (* the port is closed                      *)
  397.  
  398.          Async_Open_Flag := FALSE;
  399.          Async_XOFF_Sent := FALSE;
  400.  
  401.       END;
  402.  
  403. END    (* Async_Close *);
  404.  
  405. (*----------------------------------------------------------------------*)
  406. (*            Async_Check_CTS --- Set CTS checking on/off               *)
  407. (*----------------------------------------------------------------------*)
  408.  
  409. PROCEDURE Async_Check_CTS( CTS_Check : BOOLEAN );
  410.  
  411. (*----------------------------------------------------------------------*)
  412. (*                                                                      *)
  413. (*     Procedure:  Async_Check_CTS                                      *)
  414. (*                                                                      *)
  415. (*     Purpose:    Set CTS checking on/off                              *)
  416. (*                                                                      *)
  417. (*     Calling Sequence:                                                *)
  418. (*                                                                      *)
  419. (*        Async_Check_CTS( CTS_Check : BOOLEAN );                       *)
  420. (*                                                                      *)
  421. (*           CTS_Check --- Set TRUE to turn CTS checking ON,            *)
  422. (*                         Set FALSE to turn CTS checking OFF.          *)
  423. (*                                                                      *)
  424. (*     Calls:  None                                                     *)
  425. (*                                                                      *)
  426. (*----------------------------------------------------------------------*)
  427.  
  428. BEGIN (* Async_Check_CTS *)
  429.  
  430.    Async_Do_CTS := CTS_Check;
  431.  
  432. END   (* Async_Check_CTS *);
  433.  
  434. (*----------------------------------------------------------------------*)
  435. (*            Async_Check_DSR --- Set DSR checking on/off               *)
  436. (*----------------------------------------------------------------------*)
  437.  
  438. PROCEDURE Async_Check_DSR( DSR_Check : BOOLEAN );
  439.  
  440. (*----------------------------------------------------------------------*)
  441. (*                                                                      *)
  442. (*     Procedure:  Async_Check_DSR                                      *)
  443. (*                                                                      *)
  444. (*     Purpose:    Set DSR checking on/off                              *)
  445. (*                                                                      *)
  446. (*     Calling Sequence:                                                *)
  447. (*                                                                      *)
  448. (*        Async_Check_DSR( DSR_Check : BOOLEAN );                       *)
  449. (*                                                                      *)
  450. (*           DSR_Check --- Set TRUE to turn DSR checking ON,            *)
  451. (*                         Set FALSE to turn DSR checking OFF.          *)
  452. (*                                                                      *)
  453. (*     Calls:  None                                                     *)
  454. (*                                                                      *)
  455. (*----------------------------------------------------------------------*)
  456.  
  457. BEGIN (* Async_Check_DSR *)
  458.  
  459.    Async_Do_DSR := DSR_Check;
  460.  
  461. END   (* Async_Check_DSR *);
  462.  
  463. (*----------------------------------------------------------------------*)
  464. (*    Async_Clear_Errors --- Reset pending errors in async port         *)
  465. (*----------------------------------------------------------------------*)
  466.  
  467. PROCEDURE Async_Clear_Errors;
  468.  
  469. (*----------------------------------------------------------------------*)
  470. (*                                                                      *)
  471. (*     Procedure:   Async_Clear_Errors                                  *)
  472. (*                                                                      *)
  473. (*     Purpose:     Resets pending errors in async port                 *)
  474. (*                                                                      *)
  475. (*     Calling sequence:                                                *)
  476. (*                                                                      *)
  477. (*        Async_Clear_Errors;                                           *)
  478. (*                                                                      *)
  479. (*     Calls:  None                                                     *)
  480. (*                                                                      *)
  481. (*----------------------------------------------------------------------*)
  482.  
  483. VAR
  484.    I:  INTEGER;
  485.    M:  INTEGER;
  486.  
  487. BEGIN (* Async_Clear_Errors *)
  488.  
  489.                    (* Read the RBR and reset any pending error conditions. *)
  490.                    (* First turn off the Divisor Access Latch Bit to allow *)
  491.                    (* access to RBR, etc.                                  *)
  492.  
  493.    INLINE($FA);  (* disable interrupts *)
  494.  
  495.    Port[UART_LCR + Async_Base] := Port[UART_LCR + Async_Base] AND $7F;
  496.  
  497.                    (* Read the Line Status Register to reset any errors *)
  498.                    (* it indicates                                      *)
  499.  
  500.    I := Port[UART_LSR + Async_Base];
  501.  
  502.                    (* Read the Receiver Buffer Register in case it *)
  503.                    (* contains a character                         *)
  504.  
  505.    I := Port[UART_RBR + Async_Base];
  506.  
  507.                    (* enable the irq on the 8259 controller *)
  508.  
  509.    I := Port[I8088_IMR];  (* get the interrupt mask register *)
  510.    M := (1 SHL Async_Irq) XOR $00FF;
  511.  
  512.    Port[I8088_IMR] := I AND M;
  513.  
  514.                    (* enable the data ready interrupt on the 8250 *)
  515.  
  516.    Port[UART_IER + Async_Base] := $01;
  517.  
  518.                    (* enable OUT2 on 8250 *)
  519.  
  520.    I := Port[UART_MCR + Async_Base];
  521.    Port[UART_MCR + Async_Base] := I OR $08;
  522.  
  523.    INLINE($FB); (* enable interrupts *)
  524.  
  525. END   (* Async_Clear_Errors *);
  526.  
  527. (*----------------------------------------------------------------------*)
  528. (*    Async_Reset_Port --- Set/reset communications port parameters     *)
  529. (*----------------------------------------------------------------------*)
  530.  
  531. PROCEDURE Async_Reset_Port( ComPort       : INTEGER;
  532.                             BaudRate      : INTEGER;
  533.                             Parity        : CHAR;
  534.                             WordSize      : INTEGER;
  535.                             StopBits      : INTEGER  );
  536.  
  537. (*----------------------------------------------------------------------*)
  538. (*                                                                      *)
  539. (*     Procedure:   Async_Reset_Port                                    *)
  540. (*                                                                      *)
  541. (*     Purpose:     Resets communications port                          *)
  542. (*                                                                      *)
  543. (*     Calling Sequence:                                                *)
  544. (*                                                                      *)
  545. (*        Async_Reset_Port(   ComPort       : INTEGER;                  *)
  546. (*                            BaudRate      : INTEGER;                  *)
  547. (*                            Parity        : CHAR;                     *)
  548. (*                            WordSize      : INTEGER;                  *)
  549. (*                            StopBits      : INTEGER);                 *)
  550. (*                                                                      *)
  551. (*           ComPort  --- which port (1 or 2)                           *)
  552. (*           BaudRate --- Baud rate (110 to 9600)                       *)
  553. (*           Parity   --- "E" for even, "O" for odd, "N" for none       *)
  554. (*           WordSize --- Bits per character  (5 through 8)             *)
  555. (*           StopBits --- How many stop bits  (1 or 2)                  *)
  556. (*                                                                      *)
  557. (*     Calls:                                                           *)
  558. (*                                                                      *)
  559. (*        Async_Clear_Errors --- Clear async line errors                *)
  560. (*                                                                      *)
  561. (*----------------------------------------------------------------------*)
  562.  
  563. CONST   (* Baud Rate Constants *)
  564.  
  565.    Async_Num_Bauds = 8;
  566.  
  567.    Async_Baud_Table : ARRAY [1..Async_Num_Bauds] OF RECORD
  568.                                                        Baud, Bits : INTEGER;
  569.                                                     END
  570.  
  571.                     = ( ( Baud: 110;  Bits: $00 ),
  572.                         ( Baud: 150;  Bits: $20 ),
  573.                         ( Baud: 300;  Bits: $40 ),
  574.                         ( Baud: 600;  Bits: $60 ),
  575.                         ( Baud: 1200; Bits: $80 ),
  576.                         ( Baud: 2400; Bits: $A0 ),
  577.                         ( Baud: 4800; Bits: $C0 ),
  578.                         ( Baud: 9600; Bits: $E0 ) );
  579.  
  580. VAR
  581.    I       : INTEGER;
  582.    M       : INTEGER;
  583.    ComParm : INTEGER;
  584.  
  585. BEGIN (* Async_Reset_Port *)
  586.  
  587.             (*---------------------------------------------------*)
  588.             (*    Build the ComParm for RS232_Init               *)
  589.             (*    See Technical Reference Manual for description *)
  590.             (*---------------------------------------------------*)
  591.  
  592.                    (* Set up the bits for the baud rate *)
  593.  
  594.    IF BaudRate > 9600 THEN
  595.       BaudRate := 9600
  596.    ELSE IF BaudRate <= 0 THEN
  597.       BaudRate := 300;
  598.                                    (* Remember baud rate for purges *)
  599.    Async_Baud_Rate := BaudRate;
  600.  
  601.    I := 0;
  602.  
  603.    REPEAT
  604.       I := I + 1
  605.    UNTIL ( ( I >= Async_Num_Bauds ) OR
  606.            ( BaudRate = Async_Baud_Table[I].Baud ) );
  607.  
  608.    ComParm := Async_Baud_Table[I].Bits;
  609.  
  610.                    (* Choose Parity *)
  611.  
  612.    IF Parity In ['E', 'e'] THEN
  613.       ComParm := ComParm or $0018
  614.    ELSE IF Parity In ['O', 'o'] THEN
  615.       ComParm := ComParm or $0008;
  616.  
  617.                    (* Choose number of data bits *)
  618.  
  619.    WordSize := WordSize - 5;
  620.  
  621.    IF ( WordSize < 0 ) OR ( WordSize > 3 ) THEN
  622.       WordSize := 3;
  623.  
  624.    ComParm := ComParm OR WordSize;
  625.  
  626.                    (* Choose stop bits *)
  627.  
  628.    IF StopBits = 2 THEN
  629.       ComParm := ComParm OR $0004;  (* default is 1 stop bit *)
  630.  
  631.                    (* use the BIOS COM port initialization routine *)
  632.  
  633.    BIOS_RS232_Init( ComPort - 1 , ComParm );
  634.  
  635.                    (* Clear any pending errors on async line *)
  636.  
  637.    Async_Clear_Errors;
  638.  
  639. END   (* Async_Reset_Port *);
  640.  
  641. (*----------------------------------------------------------------------*)
  642. (*               Async_Open --- Open communications port                *)
  643. (*----------------------------------------------------------------------*)
  644.  
  645. FUNCTION Async_Open( ComPort       : INTEGER;
  646.                      BaudRate      : INTEGER;
  647.                      Parity        : CHAR;
  648.                      WordSize      : INTEGER;
  649.                      StopBits      : INTEGER  ) : BOOLEAN;
  650.  
  651. (*----------------------------------------------------------------------*)
  652. (*                                                                      *)
  653. (*     Function:   Async_Open                                           *)
  654. (*                                                                      *)
  655. (*     Purpose:    Opens communications port                            *)
  656. (*                                                                      *)
  657. (*     Calling Sequence:                                                *)
  658. (*                                                                      *)
  659. (*        Flag := Async_Open( ComPort       : INTEGER;                  *)
  660. (*                            BaudRate      : INTEGER;                  *)
  661. (*                            Parity        : CHAR;                     *)
  662. (*                            WordSize      : INTEGER;                  *)
  663. (*                            StopBits      : INTEGER) : BOOLEAN;       *)
  664. (*                                                                      *)
  665. (*           ComPort  --- which port (1 or 2)                           *)
  666. (*           BaudRate --- Baud rate (110 to 9600)                       *)
  667. (*           Parity   --- "E" for even, "O" for odd, "N" for none       *)
  668. (*           WordSize --- Bits per character  (5 through 8)             *)
  669. (*           StopBits --- How many stop bits  (1 or 2)                  *)
  670. (*                                                                      *)
  671. (*           Flag returned TRUE if port initialized successfully;       *)
  672. (*           Flag returned FALSE if any errors.                         *)
  673. (*                                                                      *)
  674. (*     Calls:                                                           *)
  675. (*                                                                      *)
  676. (*        Async_Reset_Port --- initialize RS232 port                    *)
  677. (*        DOS_Set_Intrpt   --- set address of RS232 interrupt routine   *)
  678. (*                                                                      *)
  679. (*----------------------------------------------------------------------*)
  680.  
  681. BEGIN  (* Async_Open *)
  682.                              (* IF port open, close it down first.  *)
  683.  
  684.    IF Async_Open_Flag THEN Async_Close;
  685.  
  686.                              (* Choose communications port *)
  687.    IF ComPort = 2 THEN
  688.       BEGIN
  689.          Async_Port := 2;
  690.          Async_Base := COM2_Base;
  691.          Async_Irq  := COM2_Irq;
  692.       END
  693.    ELSE
  694.       BEGIN
  695.          Async_Port := 1;  (* default to COM1 *)
  696.          Async_Base := COM1_Base;
  697.          Async_Irq  := COM1_Irq;
  698.       END;
  699.  
  700.    IF (Port[UART_IIR + Async_Base] and $00F8) <> 0 THEN
  701.       Async_Open := FALSE          (* Serial port not installed *)
  702.    ELSE
  703.       BEGIN   (* Open the port *)
  704.                                    (* Set up UART                   *)
  705.  
  706.          Async_Reset_Port( ComPort, BaudRate, Parity, WordSize, StopBits );
  707.  
  708.                                    (* Set interrupt routine address *)
  709.  
  710.          DOS_Set_Intrpt( Async_Irq + 8 , CSeg , Ofs( Async_Isr ) );
  711.  
  712.                                    (* Clear any pending errors *)
  713.          Async_Clear_Errors;
  714.  
  715.          Async_Open      := TRUE;
  716.          Async_Open_Flag := TRUE;
  717.  
  718.     END;
  719.  
  720. END   (* Async_Open *);
  721.